package algo.math.evaluator.value;

import algo.math.evaluator.base.IBase;
import algo.math.evaluator.base.exceptions.UnrecognizedToken;

/**
 * Represent a value.
 */
public class Value implements  IValue {

	private IBase _base;

	private Boolean isNegative= false;
	
	private String _integer="";
	
	private String _decimal="";
	
	private  String _buffer="";
	
	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#getIntegerValue()
	 */
	@Override
	public String getIntegerValue() {
		return _integer;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#getDecimalValue()
	 */
	@Override
	public String getDecimalValue() {
		return _decimal;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#compareTo(algo.math.evaluator.value.IValue)
	 */
	@Override
	public Compare compareTo(IValue arg0) {
		
		
		Boolean negativeComparison = false;
		
		if (this.isNegative() && !arg0.isNegative())
			{
				return Compare.INFERIOR;
			}
		else if (!this.isNegative() && arg0.isNegative())
			{
				return  Compare.SUPERIOR;
			}
		
		else if (this.isNegative() && arg0.isNegative())
			{
				negativeComparison = true;
				
				if (_integer.length()> arg0.getIntegerValue().length())
					return Compare.INFERIOR;
				
				if (_integer.length()< arg0.getIntegerValue().length())
					return Compare.SUPERIOR;
			}
		
		else
			{
				if (_integer.length()> arg0.getIntegerValue().length())
					return Compare.SUPERIOR;
				
				if (_integer.length()< arg0.getIntegerValue().length())
					return Compare.INFERIOR;
			}
		
		try
		{
		
		for (int i = 0; i<arg0.getIntegerValue().length();i++)
		{
		if (_base.valueOf(String.valueOf(_integer.charAt(i)))> _base.valueOf(String.valueOf(arg0.getIntegerValue().charAt(i))))
		{
			if (negativeComparison)
				return Compare.INFERIOR;
			
			return Compare.SUPERIOR;
		}
		
		if (_base.valueOf(String.valueOf(_integer.charAt(i)))< _base.valueOf(String.valueOf(arg0.getIntegerValue().charAt(i))))
		{
			if (negativeComparison)
				return Compare.SUPERIOR;	
			return Compare.INFERIOR;
		}
		
		}
		
		}
		
		catch (UnrecognizedToken e) {
			
			e.printStackTrace();
		}
		
		String decimalSelf= _decimal;
		String decimalOut = arg0.getDecimalValue();
		
		if (decimalSelf.length()> decimalOut.length())
		{
			while (decimalSelf.length()> decimalOut.length())
			{
				decimalOut+=_base.valueOf(0);
			}
		}
		
		if (decimalSelf.length()< decimalOut.length())
		{
			decimalSelf+=_base.valueOf(0);
		}
		try
		{
		for (int i = 0; i<decimalSelf.length();i++)
		{
		if (_base.valueOf(String.valueOf(decimalSelf.charAt(i)))> _base.valueOf(String.valueOf(decimalOut.charAt(i))))
		{
			if (negativeComparison)
				return Compare.INFERIOR;
			
			return Compare.SUPERIOR;
		}
		
		if (_base.valueOf(String.valueOf(decimalSelf.charAt(i)))< _base.valueOf(String.valueOf(decimalOut.charAt(i))))
		{
			if (negativeComparison)
				return Compare.SUPERIOR;
			
			return Compare.INFERIOR;//new String [] {op2,op1};
		}

		}
		}
		catch (UnrecognizedToken e) {
			
			e.printStackTrace();
		}
		
		
		return Compare.EQUALS; 

	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString()
	{
		if (isNegative)
		{
			return NEGATIVE_VALUE + _integer +'.'+_decimal;
		}
		return _integer +'.'+_decimal;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#setValue(java.lang.String, algo.math.evaluator.base.IBase)
	 */
	@Override
	public void setValue(String value, IBase base) throws UnrecognizedToken {
		_base = base;
		
		value = normalize(value);
		
		_integer ="";
		_decimal ="";
		
		for (int i =0; i<IBase.BLANK_CHAR.length;i++)
		{
			if (IBase.BLANK_STRING[i].equals(value))
			{
				_integer = base.valueOf(0);
				_decimal = base.valueOf(0);
			}
		}
		int swap=0;
		for (int i =0; i< value.length();i++)
		{
		
			
			if (swap==1)
			{
				_decimal+= value.charAt(i);
			}
			
			else
			{
				if (base.isSeparator(value.charAt(i)))
				{
					swap=1;
				}
				else
				{
					_integer+= value.charAt(i);
				}
			}

		}
		
		if (_integer.equals(""))
			_integer="0";
		
		if (_decimal.equals(""))
			_decimal="0";
		
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#normalize(java.lang.String)
	 */
	public  String  normalize (String value) throws UnrecognizedToken
	{
		StringBuilder sb = new StringBuilder();
		Boolean doAppend= false;
		
		if (value.length()==1 && _base.valueOf(0).equals(value))
		{
			return "0";
		}
		
		if (value.length()>0)
		{
		
			if (value.charAt(0)== NEGATIVE_VALUE)
			{
				isNegative = true;
				value = value.substring(1, value.length());
			}
		for (int i=0;i< value.length();i++)
		{
			if (_base.isSeparator(value.charAt(i)))
			{
				sb.append(value.charAt(i));
				doAppend= true;
			}
			else
			{
			if (_base.valueOf(String.valueOf(value.charAt(i)))>0 || doAppend== true)   //Char op1.charAt(i)>0)
			{
				sb.append(value.charAt(i));
				doAppend = true;
			}
			}
		}
		return sb.toString();
		}
		return "0";
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#isNegative()
	 */
	@Override
	public Boolean isNegative() {
		return isNegative;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#isZero()
	 */
	@Override
	public Boolean isZero() {
	if (_integer.equals(_base.valueOf(0))
	&&
	_decimal.equals(_base.valueOf(0))
	)
		return true;
		
	return false;
		
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#getBuffer()
	 */
	@Override
	public String getBuffer() {
		return _buffer;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#setBuffer(java.lang.String)
	 */
	@Override
	public void setBuffer(String buffer) {
		_buffer = buffer;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#isBuffered()
	 */
	@Override
	public Boolean isBuffered() {
		if (_buffer.length()>0)
			return true;
		return false;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#getSizeOfDecimal()
	 */
	@Override
	public IValue getSizeOfDecimal() {
		IValue v = new Value();
		try {
			if (_base.valueOf(_decimal)==0)
			{
				v.setValue("0", _base.getBase10());
			}
			v.setValue(String.valueOf(_decimal.length()), _base.getBase10());
		} catch (UnrecognizedToken e) {
			e.printStackTrace();
		}
		return v;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#getBase()
	 */
	@Override
	public IBase getBase() {
		return _base;
	}

	/* (non-Javadoc)
	 * @see algo.math.evaluator.value.IValue#SetIsNegative(boolean)
	 */
	@Override
	public void SetIsNegative(boolean negative) {
		isNegative =negative;
	}



}
